home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Tools / webchecker / wsgui.py < prev   
Encoding:
Python Source  |  2000-06-23  |  5.6 KB  |  245 lines

  1. #! /usr/bin/env python
  2.  
  3. """Tkinter-based GUI for websucker.
  4.  
  5. Easy use: type or paste source URL and destination directory in
  6. their respective text boxes, click GO or hit return, and presto.
  7. """
  8.  
  9. from Tkinter import *
  10. import Tkinter
  11. import string
  12. import websucker
  13. import sys
  14. import os
  15. import threading
  16. import Queue
  17. import time        
  18.  
  19. VERBOSE = 2
  20.  
  21.  
  22. try:
  23.     class Canceled(Exception):
  24.         "Exception used to cancel run()."
  25. except:
  26.     Canceled = __name__ + ".Canceled"
  27.  
  28.  
  29. class SuckerThread(websucker.Sucker):
  30.  
  31.     stopit = 0
  32.     savedir = None
  33.     rootdir = None
  34.  
  35.     def __init__(self, msgq):
  36.         self.msgq = msgq
  37.         websucker.Sucker.__init__(self)
  38.         self.setflags(verbose=VERBOSE)
  39.         self.urlopener.addheaders = [
  40.             ('User-agent', 'websucker/%s' % websucker.__version__),
  41.         ]
  42.     
  43.     def message(self, format, *args):
  44.         if args:
  45.             format = format%args
  46.         ##print format
  47.         self.msgq.put(format)
  48.  
  49.     def run1(self, url):
  50.         try:
  51.             try:
  52.                 self.reset()
  53.                 self.addroot(url)
  54.                 self.run()
  55.             except Canceled:
  56.                 self.message("[canceled]")
  57.             else:
  58.                 self.message("[done]")
  59.         finally:
  60.             self.msgq.put(None)
  61.  
  62.     def savefile(self, text, path):
  63.         if self.stopit:
  64.             raise Canceled
  65.         websucker.Sucker.savefile(self, text, path)
  66.     
  67.     def getpage(self, url):
  68.         if self.stopit:
  69.             raise Canceled
  70.         return websucker.Sucker.getpage(self, url)
  71.     
  72.     def savefilename(self, url):
  73.         path = websucker.Sucker.savefilename(self, url)
  74.         if self.savedir:
  75.             n = len(self.rootdir)
  76.             if path[:n] == self.rootdir:
  77.                 path = path[n:]
  78.                 while path[:1] == os.sep:
  79.                     path = path[1:]
  80.                 path = os.path.join(self.savedir, path)
  81.         return path
  82.  
  83.     def XXXaddrobot(self, *args):
  84.         pass
  85.  
  86.     def XXXisallowed(self, *args):
  87.         return 1
  88.  
  89.  
  90.  
  91. class App:
  92.  
  93.     sucker = None
  94.     msgq = None
  95.  
  96.     def __init__(self, top):
  97.         self.top = top
  98.         top.columnconfigure(99, weight=1)
  99.         self.url_label = Label(top, text="URL:")
  100.         self.url_label.grid(row=0, column=0, sticky='e')
  101.         self.url_entry = Entry(top, width=60, exportselection=0)
  102.         self.url_entry.grid(row=0, column=1, sticky='we',
  103.                     columnspan=99)
  104.         self.url_entry.focus_set()
  105.         self.url_entry.bind("<Key-Return>", self.go)
  106.         self.dir_label = Label(top, text="Directory:")
  107.         self.dir_label.grid(row=1, column=0, sticky='e')
  108.         self.dir_entry = Entry(top)
  109.         self.dir_entry.grid(row=1, column=1, sticky='we',
  110.                     columnspan=99)
  111.         self.go_button = Button(top, text="Go", command=self.go)
  112.         self.go_button.grid(row=2, column=1, sticky='w')
  113.         self.cancel_button = Button(top, text="Cancel",
  114.                         command=self.cancel,
  115.                                     state=DISABLED)
  116.         self.cancel_button.grid(row=2, column=2, sticky='w')
  117.         self.auto_button = Button(top, text="Paste+Go",
  118.                       command=self.auto)
  119.         self.auto_button.grid(row=2, column=3, sticky='w')
  120.         self.status_label = Label(top, text="[idle]")
  121.         self.status_label.grid(row=2, column=4, sticky='w')
  122.         self.top.update_idletasks()
  123.         self.top.grid_propagate(0)
  124.  
  125.     def message(self, text, *args):
  126.         if args:
  127.             text = text % args
  128.         self.status_label.config(text=text)
  129.  
  130.     def check_msgq(self):
  131.         while not self.msgq.empty():
  132.             msg = self.msgq.get()
  133.             if msg is None:
  134.                 self.go_button.configure(state=NORMAL)
  135.                 self.auto_button.configure(state=NORMAL)
  136.                 self.cancel_button.configure(state=DISABLED)
  137.                 if self.sucker:
  138.                     self.sucker.stopit = 0
  139.                 self.top.bell()
  140.             else:
  141.                 self.message(msg)
  142.         self.top.after(100, self.check_msgq)
  143.  
  144.     def go(self, event=None):
  145.         if not self.msgq:
  146.             self.msgq = Queue.Queue(0)
  147.             self.check_msgq()
  148.         if not self.sucker:
  149.             self.sucker = SuckerThread(self.msgq)
  150.         if self.sucker.stopit:
  151.             return
  152.         self.url_entry.selection_range(0, END)
  153.         url = self.url_entry.get()
  154.         url = string.strip(url)
  155.         if not url:
  156.             self.top.bell()
  157.             self.message("[Error: No URL entered]")
  158.             return
  159.         self.rooturl = url
  160.         dir = string.strip(self.dir_entry.get())
  161.         if not dir:
  162.             self.sucker.savedir = None
  163.         else:
  164.             self.sucker.savedir = dir
  165.             self.sucker.rootdir = os.path.dirname(
  166.                 websucker.Sucker.savefilename(self, url))
  167.         self.go_button.configure(state=DISABLED)
  168.         self.auto_button.configure(state=DISABLED)
  169.         self.cancel_button.configure(state=NORMAL)
  170.         self.message( '[running...]')
  171.         self.sucker.stopit = 0
  172.         t = threading.Thread(target=self.sucker.run1, args=(url,))
  173.         t.start()
  174.     
  175.     def cancel(self):
  176.         if self.sucker:
  177.             self.sucker.stopit = 1
  178.         self.message("[canceling...]")
  179.     
  180.     def auto(self):
  181.         tries = ['PRIMARY', 'CLIPBOARD']
  182.         text = ""
  183.         for t in tries:
  184.             try:
  185.                 text = self.top.selection_get(selection=t)
  186.             except TclError:
  187.                 continue
  188.             text = string.strip(text)
  189.             if text:
  190.                 break
  191.         if not text:
  192.             self.top.bell()
  193.             self.message("[Error: clipboard is empty]")
  194.             return
  195.         self.url_entry.delete(0, END)
  196.         self.url_entry.insert(0, text)
  197.         self.go()
  198.  
  199.  
  200. class AppArray:
  201.  
  202.     def __init__(self, top=None):
  203.         if not top:
  204.             top = Tk()
  205.             top.title("websucker GUI")
  206.             top.iconname("wsgui")
  207.             top.wm_protocol('WM_DELETE_WINDOW', self.exit)
  208.         self.top = top
  209.         self.appframe = Frame(self.top)
  210.         self.appframe.pack(fill='both')
  211.         self.applist = []
  212.         self.exit_button = Button(top, text="Exit", command=self.exit)
  213.         self.exit_button.pack(side=RIGHT)
  214.         self.new_button = Button(top, text="New", command=self.addsucker)
  215.         self.new_button.pack(side=LEFT)
  216.         self.addsucker()
  217.         ##self.applist[0].url_entry.insert(END, "http://www.python.org/doc/essays/")
  218.  
  219.     def addsucker(self):
  220.         self.top.geometry("")
  221.         frame = Frame(self.appframe, borderwidth=2, relief=GROOVE)
  222.         frame.pack(fill='x')
  223.         app = App(frame)
  224.         self.applist.append(app)
  225.  
  226.     done = 0
  227.  
  228.     def mainloop(self):
  229.         while not self.done:
  230.             time.sleep(0.1)
  231.             self.top.update()
  232.     
  233.     def exit(self):
  234.         for app in self.applist:
  235.             app.cancel()
  236.             app.message("[exiting...]")
  237.         self.done = 1
  238.  
  239.  
  240. def main():
  241.     AppArray().mainloop()
  242.  
  243. if __name__ == '__main__':
  244.     main()
  245.